#include "videoreceiver.h"
#include <QDebug>
#include <QApplication>
#include <QFile>
#include <QTimer>
#include <QDir>
#include <QTextStream>

VideoReceiver::VideoReceiver(QObject *parent) : QObject(parent),
    ffplayProcess(nullptr), videoWidget(nullptr), isReceivingFlag(false)
{
    // 设置默认参数 - 使用多播地址（跨机器）
    multicastAddress = "224.1.1.1";  // 使用多播地址
    port = 5004;
    
    setupFFplayProcess();
}

VideoReceiver::~VideoReceiver()
{
    if (isReceivingFlag) {
        stopReceiving();
    }
    
    if (ffplayProcess) {
        ffplayProcess->deleteLater();
    }
}

bool VideoReceiver::initialize()
{
    if (!ffplayProcess) {
        setupFFplayProcess();
    }
    
    qDebug() << "视频接收器初始化完成";
    return true;
}

void VideoReceiver::setMulticastAddress(const QString& address, int newPort)
{
    multicastAddress = address;
    port = newPort;
}

void VideoReceiver::setVideoWidget(QWidget* widget)
{
    videoWidget = widget;
}

bool VideoReceiver::startReceiving()
{
    if (isReceivingFlag) {
        return false;
    }
    
    qDebug() << "开始接收视频流...";
    
    // 构建FFplay参数
    buildFFplayArguments();
    
    // 启动FFplay进程
    QString ffplayPath = "/usr/bin/ffplay";
    if (!QFile::exists(ffplayPath)) {
        ffplayPath = "ffplay"; // 回退到PATH查找
    }
    
    // 调试：输出完整命令
    // QString command = ffplayPath + " " + ffplayArguments.join(" ");
    // qDebug() << "FFplay命令:" << command;
    
    ffplayProcess->start(ffplayPath, ffplayArguments);
    
    if (ffplayProcess->waitForStarted(5000)) {
        qDebug() << "FFplay进程启动成功，进程ID:" << ffplayProcess->processId();
        qDebug() << "等待视频流连接...";
        
        // 强制检测：1秒后如果FFplay还在运行就认为连接成功
        QTimer::singleShot(1000, [this]() {
            if (!isReceivingFlag && ffplayProcess && ffplayProcess->state() == QProcess::Running) {
                isReceivingFlag = true;
                // qDebug() << "FFplay进程持续运行1秒，强制设置连接状态为已连接";
                emit receivingStarted();
            }
        });
        
        return true;
    } else {
        qDebug() << "VideoReceiver: FFplay进程启动失败:" << ffplayProcess->errorString();
        emit errorOccurred("FFplay进程启动失败");
        return false;
    }
}

void VideoReceiver::stopReceiving()
{
    if (!isReceivingFlag) {
        return;
    }
    
    qDebug() << "停止接收视频流...";
    
    if (ffplayProcess && ffplayProcess->state() == QProcess::Running) {
        // 优雅停止FFplay
        ffplayProcess->terminate();
        
        if (!ffplayProcess->waitForFinished(5000)) {
            // 如果5秒内没有停止，强制终止
            ffplayProcess->kill();
            ffplayProcess->waitForFinished();
        }
    }
    
    isReceivingFlag = false;
    emit receivingStopped();
    qDebug() << "视频接收已停止";
}

bool VideoReceiver::isReceiving() const
{
    return isReceivingFlag;
}

void VideoReceiver::setupFFplayProcess()
{
    ffplayProcess = new QProcess(this);
    
    // 连接FFplay进程信号
    connect(ffplayProcess, &QProcess::finished, this, &VideoReceiver::onFFplayFinished);
    connect(ffplayProcess, &QProcess::errorOccurred, this, &VideoReceiver::onFFplayError);
    
    // 连接FFplay输出信号，用于检测视频流
    connect(ffplayProcess, &QProcess::readyReadStandardOutput, this, &VideoReceiver::onFFplayOutput);
    connect(ffplayProcess, &QProcess::readyReadStandardError, this, &VideoReceiver::onFFplayErrorOutput);
}

void VideoReceiver::buildFFplayArguments()
{
    ffplayArguments.clear();
    
    // 调试：输出接收参数
    // qDebug() << "构建FFplay参数，多播地址:" << multicastAddress << "端口:" << port;
    
    // 自动创建SDP文件
    createSDPFile();
    
    // 基本播放参数 - 使用SDP文件接收多播，优化网络接收
    ffplayArguments << "-fflags" << "nobuffer+discardcorrupt"  // 无缓冲+丢弃损坏帧
                   << "-flags" << "low_delay"          // 低延迟
                   << "-framedrop"                     // 丢帧
                   << "-sync" << "ext"                 // 外部时钟同步
                   << "-protocol_whitelist" << "file,rtp,udp"  // 允许的协议
                   << "-hide_banner"                   // 隐藏横幅
                   << "-loglevel" << "warning"        // 仅警告级别，减少日志
                   << "-max_delay" << "500000"         // 最大延迟500ms
                   << "-reorder_queue_size" << "0"     // 禁用重排序队列
                   << "-i" << "/tmp/stream.sdp";  // 使用自动创建的SDP文件
    
    // 显示参数
    if (videoWidget) {
        // 如果有视频组件，设置窗口标题
        ffplayArguments << "-window_title" << "电子教室视频流";
    } else {
        // 如果没有视频组件，也要设置窗口标题
        ffplayArguments << "-window_title" << "电子教室视频流";
    }
    
    // 性能优化参数
    ffplayArguments << "-threads" << "4";              // 使用4线程
}

void VideoReceiver::onFFplayFinished(int exitCode, QProcess::ExitStatus exitStatus)
{
    qDebug() << "VideoReceiver: FFplay进程结束，退出码:" << exitCode << ", 状态:" << exitStatus;
    
    if (isReceivingFlag) {
        // 如果之前已经连接成功，现在断开连接
        isReceivingFlag = false;
        emit receivingStopped();
        qDebug() << "视频流连接断开";
    }
    
    if (exitStatus == QProcess::CrashExit) {
        emit errorOccurred("FFplay进程崩溃");
    } else if (exitCode != 0) {
        // 非零退出码，通常是连接失败
        if (exitCode == 123) {
            emit errorOccurred("无法连接到视频流，请检查教师端是否启动");
        } else {
            emit errorOccurred(QString("FFplay连接失败，退出码: %1").arg(exitCode));
        }
    } else {
        // 正常退出，可能是用户手动停止
        qDebug() << "FFplay正常退出";
    }
}

void VideoReceiver::onFFplayError(QProcess::ProcessError error)
{
    QString errorStr;
    switch (error) {
        case QProcess::FailedToStart:
            errorStr = "FFplay进程启动失败";
            break;
        case QProcess::Crashed:
            errorStr = "FFplay进程崩溃";
            break;
        case QProcess::Timedout:
            errorStr = "FFplay进程超时";
            break;
        default:
            errorStr = "FFplay未知错误";
            break;
    }
    
    qDebug() << "FFplay进程错误:" << errorStr;
    emit errorOccurred(errorStr);
}

void VideoReceiver::onFFplayOutput()
{
    const QString output = QString::fromUtf8(ffplayProcess->readAllStandardOutput());
    
    // 检测是否接收到真正的视频帧数据
    if (output.contains("frame=") && output.contains("fps=")) {
        if (!isReceivingFlag) {
            isReceivingFlag = true;
            // qDebug() << "检测到真正的视频流(标准输出)，设置连接状态为已连接";
            emit receivingStarted();
        }
    }
    
    // 如果FFplay进程正在运行，也认为连接成功
    if (!isReceivingFlag && ffplayProcess && ffplayProcess->state() == QProcess::Running) {
        // 延迟2秒后如果FFplay还在运行，就认为连接成功
        QTimer::singleShot(2000, [this]() {
            if (!isReceivingFlag && ffplayProcess && ffplayProcess->state() == QProcess::Running) {
                isReceivingFlag = true;
                // qDebug() << "FFplay进程持续运行，设置连接状态为已连接";
                emit receivingStarted();
            }
        });
    }
}

void VideoReceiver::onFFplayErrorOutput()
{
    const QString errorOutput = QString::fromUtf8(ffplayProcess->readAllStandardError());
    
    // 检测是否接收到真正的视频帧数据
    if (errorOutput.contains("frame=") && errorOutput.contains("fps=")) {
        if (!isReceivingFlag) {
            isReceivingFlag = true;
            // qDebug() << "检测到真正的视频流(错误输出)，设置连接状态为已连接";
            emit receivingStarted();
        }
    } else if (errorOutput.contains("Could not find codec parameters") || 
               errorOutput.contains("Invalid data found when processing input") ||
               errorOutput.contains("No such file or directory")) {
        // 明确提示教师端未启动或SDP不匹配
        // qDebug() << "FFplay错误: 输入流无效或教师端未启动";
    } else if (errorOutput.contains("Video:") && !errorOutput.contains("frame=")) {
        // 只是SDP解析信息，不是真正的视频流
        // qDebug() << "FFplay: 检测到SDP信息，等待真正的视频流...";
    }
}

void VideoReceiver::createSDPFile()
{
    // 自动创建SDP文件
    QStringList sdpPaths = {
        "/tmp/stream.sdp",                    // Linux临时目录
        "/var/tmp/stream.sdp",                // 系统临时目录
        QDir::homePath() + "/stream.sdp",     // 用户主目录
        QDir::currentPath() + "/stream.sdp"   // 当前目录
    };
    
    for (const QString& sdpPath : sdpPaths) {
        QFile sdpFile(sdpPath);
        if (sdpFile.open(QIODevice::WriteOnly | QIODevice::Text)) {
            QTextStream out(&sdpFile);
            out << "v=0\n";
            out << "o=- 0 0 IN IP4 224.1.1.1\n";
            out << "s=Electronic Classroom Stream\n";
            out << "c=IN IP4 224.1.1.1\n";
            out << "t=0 0\n";
            out << "m=video 5004 RTP/AVP 96\n";
            out << "a=rtpmap:96 H264/90000\n";
            out << "a=recvonly\n";
            sdpFile.close();
            // qDebug() << "学生端自动创建SDP文件成功:" << sdpPath;
        }
    }
}
